use crate::mimalloc::utils::MemoryBlock;
use std::alloc::{GlobalAlloc, Layout};
use std::sync::atomic::AtomicPtr;

/// 内存分配器主结构
pub struct MiMalloc {
    pub(crate) free_lists: [AtomicPtr<MemoryBlock>; 3],
}

unsafe impl GlobalAlloc for MiMalloc {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        let category = Self::categorize_chunk(layout.size());
        let free_list = self.get_free_list(category);

        // 尝试从空闲列表分配
        let ptr = self.allocate_from_free_list(free_list, layout);

        // 如果分配失败，使用系统分配
        let result = if ptr.is_null() {
            Self::system_alloc(layout.size())
        } else {
            ptr
        };

        result
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        if !ptr.is_null() {
            self.free_to_list(ptr, layout);
        }
    }

    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
        // 分配新的内存块
        let new_ptr = self.alloc(Layout::from_size_align(new_size, layout.align()).unwrap());

        if !new_ptr.is_null() && !ptr.is_null() {
            // 复制旧数据
            std::ptr::copy_nonoverlapping(ptr, new_ptr, std::cmp::min(layout.size(), new_size));

            // 释放旧内存块
            self.dealloc(ptr, layout);
        }

        new_ptr
    }
}
